// Text of project ListPickerNewEntry written on 5/23/96 at 9:47 AM
// Beginning of text file ProjectData
/*
**      Newton Developer Technical Support Sample Code
**
**     	ListPicker,  The listPicker that uses a user defined soup and 
**		allows for new entries to be added.
**
**      by Stephen Harris, Newton Developer Technical Support
**
**      Copyright  1993-1996 by Apple Computer, Inc.  All rights reserved.
**
**      You may incorporate this sample code into your applications without
**      restriction.  This sample code has been provided "AS IS" and the
**      responsibility for its operation is 100% yours.  You are not
**      permitted to modify and redistribute the source as "DTS Sample Code."
**      If you are going to re-distribute the source, we require that you
**      make it clear in the source that the code was descended from
**      Apple-provided sample code, but that you've made changes.
*/

//  This sample demonstates the use of the protoListPicker and a user defined soup and give the
//  user the option to add new items to the soup.

// the app stuff
constant kAppTitle := "The List Picker";

//--------------

// Soup stuff
constant kSoupName := kPackageName;
Constant kSoupIndexes := '[{structure: slot,path: first, type: string}];

// for listPicker query
constant kQuerySpec := '{type: index, indexpath: first};

// used by the regUnionSoup function
DefConst('kSoupDef, {
	name: kSoupName,
	username: kAppName,
	ownerApp: kAppSymbol,
	userDescr: "The user soup for the ListPicker sample",
	indexes: kSoupIndexes
}) ;

//--------------


// Random  entry generator.
DefConst('kCanonicalEntry,
   {
		first: nil,
		second: nil,

	});


DefConst('kRandomDataGeneratorFunc, func()
	begin
		local item := clone(kCanonicalEntry);

		item.first := Capitalize(GetRandomWord(4, 12));
		item.second := Capitalize(GetRandomWord(4, 12));
		item;
	end);
		
//--------------

// DeleteScript->  this only gets called when your app is deleted and not
// when the card is removed.
SetPartFrameSlot('DeletionScript, func()
	begin
		//Remove the soup from the stores
		foreach store in GetStores() do 
		begin
			local theSoup := store:GetSoup(kSoupName);
			if theSoup then
			   theSoup:RemoveFromStore();
		end;
	end
);


// Install/Remove Scripts

InstallScript := func(part)
begin	
	RegUnionSoup(kAppSymbol, kSoupDef) ;
end;

RemoveScript := func(part)
begin
	// unregister autocreation of soup
	UnRegUnionSoup(kSoupName, kAppSymbol);
end;
// End of text file ProjectData
// Beginning of file editor.t

// Before Script for "editBase"
// Copyright  1993-1996 by Apple Computer, Inc.  All rights reserved.
// this code will be executed before the template is processed


editBase :=
    {viewBounds: {left: -4, top: 46, right: 184, bottom: 138},
     new:
       func(nameRef, editPaths, why, pickerDef, callback, context) begin
       
       	local view := BuildContext(self);
       	
       	view.nameRef		:= nameRef;
       	view.context		:= context;
       	view.callback		:= callback;
       	view.pickerDef		:= pickerDef;
       	view.editPaths		:= editPaths;
       	view.reasonForOpen	:= why;
       	
       	view:Open();
       	
       	view;
       end,
     title: nil,
     viewSetupFormScript:
       func()
       begin
       	// set a title that is what we are doing
       	if reasonForOpen = 'new then
       		title := "New "
       	else
       		title := "Edit " ;
       	
       	title := title & pickerDef.name ;
       end,
     callback: nil,
     context: nil,
     editPaths: nil,
     nameRef: nil,
     pickerDef: nil,
     reasonForOpen: nil,
     viewQuitScript:
       // must return the value of inherited:?viewQuitScript();
       func()
       begin
       	nameRef.first := Clone(first.entryLine.text) ;
       	nameRef.second := Clone(second.entryLine.text) ;
       
       	Perform(pickerDef, callback, [nameRef, editpaths, context, reasonForOpen]);
       
       	nameRef 			:= nil ;
       	context			:= nil ;
       	callback			:= nil ;
       	pickerDef		:= nil ;
       	editPaths		:= nil ;
       	reasonForOpen	:= nil ;
       
       	inherited:?viewQuitScript();		// this method is defined internally
       end,
     debug: "editBase",
     _proto: @180
    };

_view000 :=
    {viewBounds: {left: -2, top: 0, right: 78, bottom: 16}, _proto: @229};
AddStepForm(editBase, _view000);



first :=
    {viewBounds: {left: 8, top: 24, right: 168, bottom: 48},
     label: "First",
     textSetup:
       func()
       begin
       	if nameRef.first then
       		Clone(nameRef.first) ;
       	else
       		Clone("") ;
       end,
     debug: "first",
     _proto: @189
    };
AddStepForm(editBase, first);
StepDeclare(editBase, first, 'first);



second :=
    {viewBounds: {left: 8, top: 56, right: 168, bottom: 80},
     label: "Second",
     textSetup:
       func()
       begin
       	if nameRef.second then
       		Clone(nameRef.second) ;
       	else
       		Clone("") ;
       end,
     debug: "second",
     _proto: @189
    };
AddStepForm(editBase, second);
StepDeclare(editBase, second, 'second);




constant |layout_editor.t| := editBase;
// End of file editor.t
// Beginning of text file pickerDef.f
//Copyright  1993-1995 by Apple Computer, Inc.  All rights reserved.

// listPicker defs

// a validation frame is required to support editing. The frame is used
// in the pickerDef.
DefConst('kValidationFrame,
	{
		first:						// fieldpath of listPicker display item.
		{
			inputProto:
			{							// the line in the defaultOpenEditor
				_proto: newtLabelInputLine,		// protonewtlabelinputline := @422
			},
			theText: "First",		// label for the editLine of the defaultOpenEditor
			type: 'text,			// could be of other type such as 'number or 'shape
		},

		second:
		{
			inputProto:
			{
				_proto: newtLabelInputLine,
			},
			theText: "Second",
			type: 'text,
		},
	});


//used to define the pickerDef at compile time.  May include all of the slots for the pickerDef.
//In the listPicker.pickerDef proto to this DataDef.  
DefConst('kMySoupDataDef,{
	_proto: protoNameRefDataDef,				// Required
	name:  "Random Data ",						// name at top left of picker
	
	// the following stuff is required for validation
	Validate: func(nameRef, pathArray)
	begin
		// keep track of any paths that fail
		local failedPaths := [];
		foreach index, path in pathArray do
		begin
			// very simple test since each path is
			// is supposed to be a string
			// your test may be more complex and call
			// other methods to verify particular types of data
			if NOT :ValidateString(nameRef, path) then
				AddArraySlot(failedPaths, path) ;
			// return the failedPaths or an empty array
		end;
		return failedPaths ;	
	end,
	
	// my own utility function to make sure the string is valid
	// used :Validate above
	ValidateString: func(nameRef, path)
	begin
		// try and get the data from the nameRef
		local realData := nameRef.(path) ;
		
		// if not data in the nameRef, try and get
		// the entry and get the data from it
		if NOT realData then
		begin
			entry := EntryFromObj(nameRef) ;
			if entry then
			begin
				realData := entry.(path) ;
				nameRef.(path) := realData ;
			end ;
		end ;
		
		// valid if the value is non-NIL and is a filled string
		return realData AND IsString(realData) AND StrFilled(realData) ;
	end,
	
	
	// provide this method to open an edit slip for
	// a new or editited item.
	OpenEditor: func(tapInfo, context, why)
	begin
		local valid := :Validate(tapInfo.nameRef, tapInfo.editPaths) ;
		
		// check to see if the nameRef is valid to figure out
		// what to do
		if (length(valid) > 0) then
		begin
			// if not valid, open the editor
			return GetLayout("editor.t"):New(tapinfo.nameRef,
				tapInfo.editPaths, why, self, 'EditDone, context) ;
		end
		else begin
			// just toggle the selection and return nil
			context:Tapped('toggle) ;
			return nil ;
		end ;
	end,
	
	// this is a utility method that is not part of the required
	// methods. Once the editor is closed, this method gets
	// called so we can update the listPicker appropriately
	EditDone: func(nameRef, editPaths, context, why)
	begin
		// check to see if the edited item is valid
		if NOT :Validate(nameRef, editPaths) then
			// not valid so remove the checkmark (if any)
			context:Tapped(nil);
		else begin
			// is valid, so see if editing or a new item
			if why = 'edit then
			begin
				// change the actual entry
				// an edit occurs when the entry that is clicked
				// on does not Validate.
				local entry := EntryFromObj(nameRef) ;
				if entry then
				begin
					entry.first := nameRef.first ;
					entry.second := nameRef.second ;
					EntryChangeXMIT(entry, kAppSymbol) ;
				end ;
				
				// The nameRef was valid, so select it.
				context:Tapped('select);
			end
			else begin
				// a new data item so add entry to soup
				local newEntry := Clone(kCanonicalEntry) ;
				newEntry.first := nameRef.first ;
				newEntry.second := nameRef.second ;

				GetUnionSoupAlways(kSoupName):AddToDefaultStoreXMIT(newEntry, kAppSymbol) ;
				
				// tell the listpicker to update its information
				context:Update() ;
			end ;
		end ;
	end,
	
	});
	

//************

/*
	removed validationFrame slot from data def
*/
// End of text file pickerDef.f
// Beginning of file ListPickerSoupNew.t
appBase :=
    {viewBounds: {left: 0, top: 0, right: 240, bottom: 320},
     viewFlags: 1,
     viewFormat: 0,
     declareSelf: 'base,
     viewJustify: 0,
     viewSetupFormScript:
       func()
       begin
       	//set up app display
       	local b := GetAppParams();
       	self.viewBounds := RelBounds(b.appAreaLeft, b.appAreaTop,
       		b.appAreaWidth, b.appAreaHeight);
       	
       	if NOT reOrienting then
       	begin
       		//set up soup
       		theSoup := GetUnionSoupAlways(kSoupName); 
       		local theCursor := theSoup:Query(kQuerySpec);
       		
       		//make random Entries if there are none in the soup
       		if theCursor:Entry() = nil then
       			:GenerateData();
       	end;
       end,
     theSoup: nil,
     GenerateData:
       func()
       begin
       	// get a local for the array invariant
       	local mySoup := theSoup ;
       
       	for i := 0 to 19 do
       		mySoup:AddToDefaultStore(call kRandomDataGeneratorFunc with ());
       end,
     viewQuitScript:
       func()
       begin
       	//memory reclaim
       	theSoup:= nil;
       end,
     ReorientToScreen:
       func()
       begin
       	reOrienting := true ;
       	:syncView();
       	:RedoChildren();
       	reOrienting := nil ;
       end,
     reOrienting: nil,
     debug: "appBase",
     viewClass: 74
    };

_view001 :=
    {title: kAppTitle,
     viewBounds: {left: 0, top: 0, right: 150, bottom: 20},
     _proto: @229
    };
AddStepForm(appBase, _view001);



mylistpicker :=
    {viewFlags: 513,
     viewBounds: {left: 0, top: 20, right: 0, bottom: -70},
     viewJustify: 240,
     pickerDef:
       {
       	_proto: kMySoupDataDef,				//your defined pickerDef
       	class:  'nameRef,						//required
       	
       	//the items to be displayed in the listPicker
       	columns:
       	[
       		// Column 1
       		{
       			fieldPath: 'first,		// field to display in column
       			tapWidth: 120,				// width for checkbox & name combined
       			
       			doRowHilite: true,
       		},
       		
       		// Column 2
       		{
       			fieldPath: 'second,		// field to display in column
       			tapWidth: 0,				// width for checkbox & name combined
       			
       			doRowHilite: true,
       		},
       		
       	],
       },
     querySpec: kQuerySpec,
     soupToQuery: kSoupName,
     selected: nil,
     suppressFolderTabs: true,
     suppressCloseBox: true,
     viewQuitScript:
       func()
       begin
       	//when dealing with soups ensure that the listPicker is torn down after closing if 
       	//it will be opened again later.
       	selected:= nil;
       	inherited:viewQuitScript();
       end,
     debug: "mylistpicker",
     _proto: @461
    };
AddStepForm(appBase, mylistpicker);
StepDeclare(appBase, mylistpicker, 'mylistpicker);



_view002 :=
    {
     buttonClickScript:
       func()
       begin
       	:GenerateData();
       	mylistPicker:Update();	
       end,
     text: "Add more Data",
     viewBounds: {left: 0, top: 6, right: 100, bottom: 24},
     viewJustify: 8396950
     ,
     _proto: @226
    };
AddStepForm(appBase, _view002);



_view003 :=
    {
     buttonClickScript:
       func()
       begin
       	whatSelected:open();
       end,
     text: "What is selected",
     viewBounds: {left: 0, top: 6, right: 100, bottom: 24},
     viewJustify: 8396950
     ,
     _proto: @226
    };
AddStepForm(appBase, _view003);



_view004 := {_proto: @401};
AddStepForm(appBase, _view004);



whatSelected :=
    {viewBounds: {left: -1, top: 72, right: 106, bottom: 188},
     debug: "whatSelected",
     _proto: @180
    };
AddStepForm(appBase, whatSelected);
StepDeclare(appBase, whatSelected, 'whatSelected);

_view005 :=
    {
     buttonClickScript:
       func(textIndex)
       begin
       	print("selected index " & textIndex);
       end,
     viewBounds: {left: 0, top: 0, right: 0, bottom: 116},
     viewFont: ROM_fontSystem9,
     viewLines: 6,
     viewSetupFormScript:
       func()
       begin
       	// call the getSelected fucntion with true to return only the items
       	// that are currently selected'
       	// NOTE: as items are selected nameRef's are created and put in the selected array. 
       	// GetSelected returns an array of the selected items and removes all other nameRef's
       		
       	local myArray := [];
       	foreach item in myListPicker:getSelected(true) do
       		AddArraySlot(myArray,(item.first && item.second));
       
       	self.listItems := myArray;
       
       	:SetupList();
       end,
     listItems: nil,
     viewJustify: 48,
     viewFormat: 1,
     useScrollers: true,
     _proto: @228
    };
AddStepForm(whatSelected, _view005);





// After Script for "appBase"
thisView := appBase;
// Copyright  1993-1996 by Apple Computer, Inc.  All rights reserved.



constant |layout_ListPickerSoupNew.t| := appBase;
// End of file ListPickerSoupNew.t



